using System;
using System.Collections.Generic;
using System.Text;
using SharpGen.Common;
using System.IO;

namespace SharpGen.TemplateInterface
{
    //public class TemplateExample : ICodeGenTemplate
    //{
    //    #region Private properties
    //    SqlObject _currentObject = null;
    //    string entityRowCollectionClassName;
    //    string entityRowClassName;
    //    #endregion

    //    #region public TemplateExample()
    //    /// <summary>
    //    /// Initializes a new instance of the <b>TemplateExample</b> class.
    //    /// </summary>
    //    /// <remarks>This sonstructor is called by the Host Application.</remarks>
    //    public TemplateExample()
    //    {

    //    }
    //    #endregion

    //    #region Generated
    //    #region private void EntryPointGenerated(SharpCodeProvider codeProvider)
    //    /// <summary>
    //    /// Entry point for the template.
    //    /// </summary>
    //    /// <param name="codeProvider"></param>
    //    /// <remarks>This method is called by the Initialize method.</remarks>
    //    private void EntryPointGenerated(SharpCodeProvider codeProvider)
    //    {
    //        codeProvider.WriteUsing("System");
    //        codeProvider.WriteUsing("System.Collections.Generic");
    //        codeProvider.WriteUsing("System.Data");
    //        codeProvider.WriteUsing("ICFramework.Business.DataLayer");
    //        codeProvider.WriteUsing("ICFramework.Common.DataLayer");
    //        codeProvider.WriteNamespace(Host.OutNamespace, new SharpCodeProvider.WriterDelegate[] { classNS });
    //    }
    //    #endregion

    //    private void classNS(SharpCodeProvider codeProvider, object data)
    //    {
    //        ITable table = _currentObject.Data as ITable;
    //        codeProvider.WriteAttribute("Entity", new string[] { table.Name });

    //        entityRowCollectionClassName = string.Format("{0}RowCollection", _currentObject.ClassName);
    //        entityRowClassName = string.Format("{0}Row", _currentObject.ClassName);
    //        codeProvider.WriteClass(new AccessModifiers[] { AccessModifiers.amPublic }, true, _currentObject.ClassName, string.Format("EntityBase<{0}, {1}>", _currentObject.ClassName, entityRowClassName), new SharpCodeProvider.WriterDelegate[] { classGeneration });
    //        codeProvider.WriteClass(new AccessModifiers[] { AccessModifiers.amPublic }, true, entityRowCollectionClassName, string.Format("EntityRowCollection<{0}, {1}>", _currentObject.ClassName, entityRowClassName), new SharpCodeProvider.WriterDelegate[] { classRowCollectionGeneration });
    //        codeProvider.WriteClass(new AccessModifiers[] { AccessModifiers.amPublic }, true, entityRowClassName, string.Format("EntityRow<{0}, {1}>", _currentObject.ClassName, entityRowClassName), new SharpCodeProvider.WriterDelegate[] { classRowGeneration });
    //    }

    //    private void classGeneration(SharpCodeProvider codeProvider, object data)
    //    {
    //        switch (_currentObject.ObjectType)
    //        {
    //            case CodeGen.Enums.SqlObjectType.Table:
    //            case CodeGen.Enums.SqlObjectType.View:
    //                GenerateTableClass(codeProvider, (string)data);
    //                break;
    //            case CodeGen.Enums.SqlObjectType.StoredProcedure:
    //                break;
    //            default:
    //                break;
    //        }
    //    }

    //    #region EntityClass
    //    public void GenerateTableClass(SharpCodeProvider codeProvider, string className)
    //    {
    //        ITable table = _currentObject.Data as ITable;
    //        foreach (IColumn col in table.Columns)
    //        {
    //            string prvFieldValue = string.Format("new EntityColumn(\"{0}\", DbType.{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9})",
    //                col.Name,
    //                col.DataType.DbType.ToString(),
    //                col.InPrimaryKey.ToString().ToLower(),
    //                col.IsForeignKey.ToString().ToLower(),
    //                col.Nullable.ToString().ToLower(),
    //                col.DataType.MaximumLength.HasValue ? col.DataType.MaximumLength.Value.ToString() : "null",
    //                col.DataType.NumericPrecision.HasValue ? col.DataType.NumericPrecision.Value.ToString() : "null",
    //                col.DataType.NumericScale.HasValue ? col.DataType.NumericScale.Value.ToString() : "null",
    //                string.IsNullOrEmpty(col.Default) ? "null" : "new object()",
    //                col.ReadOnly.ToString().ToLower());
    //            codeProvider.WriteField(new AccessModifiers[] { AccessModifiers.amPrivate }, "EntityColumn", codeProvider.GetPrivatePropertyName(col.Name), prvFieldValue);
    //            codeProvider.WriteProperty(new AccessModifiers[] { AccessModifiers.amPublic }, "EntityColumn", col.Name, false, codeProvider.GetPrivatePropertyName(col.Name), false);
    //        }
    //        codeProvider.WriteConstructor(new AccessModifiers[] { AccessModifiers.amPublic }, className, null, null, TableConstructorContent, new string[] { string.Format("typeof({0})", className) });
    //        codeProvider.WriteMethod(new AccessModifiers[] { AccessModifiers.amPrivate }, null, "InitializeEntity", null, null, InitializeEntityContent);
    //        codeProvider.WriteProperty(new AccessModifiers[] { AccessModifiers.amPublic, AccessModifiers.amOverride }, string.Format("EntityRowCollection<{0}, {0}Row>", className), "Rows", false, "_rows", true);
    //        codeProvider.WriteMethod(new AccessModifiers[] { AccessModifiers.amPublic }, null, "Refresh", null, null, RefreshContent);
    //        codeProvider.WriteMethod(new AccessModifiers[] { AccessModifiers.amNA }, null, string.Format("{0}_DataTableChanged", _currentObject.ClassName), new string[] { "object", "EventArgs" }, new string[] { "sender", "e" }, DataChangedContent);
    //    }

    //    public void DataChangedContent(SharpCodeProvider codeProvider, object data)
    //    {
    //        codeProvider.WriteMethodCall("Refresh", null);
    //    }

    //    public void RefreshContent(SharpCodeProvider codeProvider, object data)
    //    {
    //        codeProvider.WriteCodeLine("_rows.Clear();");
    //        codeProvider.WriteCodeLine("foreach (DataRow dr in _table.Rows)");
    //        codeProvider.WriteBegin();
    //        codeProvider.WriteCodeLine(string.Format("{0}Row eRow = new {0}Row(dr, this);", _currentObject.ClassName));
    //        codeProvider.WriteCodeLine("eRow.DataRow = dr;");
    //        codeProvider.WriteCodeLine("_rows.Add(eRow);");
    //        codeProvider.WriteEnd();
    //    }

    //    public void InitializeEntityContent(SharpCodeProvider codeProvider, object data)
    //    {
    //        ITable table = _currentObject.Data as ITable;
    //        foreach (IColumn col in table.Columns)
    //        {
    //            codeProvider.Writer.WriteLine("_columns.Add({0});", codeProvider.GetPrivatePropertyName(col.Name));
    //        }
    //        codeProvider.WriteAddEvent("base.DataTableChanged", null, string.Format("{0}_DataTableChanged", _currentObject.ClassName));
    //    }

    //    public void TableConstructorContent(SharpCodeProvider codeProvider, object data)
    //    {
    //        codeProvider.WriteMethodCall("InitializeEntity", null);
    //        codeProvider.WriteAssignment("_rows", string.Format("new {0}RowCollection(this, _columns)", _currentObject.ClassName));
    //    }
    //    #endregion

    //    #region RowCollection Class

    //    private void classRowCollectionGeneration(SharpCodeProvider codeProvider, object data)
    //    {
    //        switch (_currentObject.ObjectType)
    //        {
    //            case CodeGen.Enums.SqlObjectType.Table:
    //            case CodeGen.Enums.SqlObjectType.View:
    //                GenerateTableRowCollectionClass(codeProvider, (string)data);
    //                break;
    //            case CodeGen.Enums.SqlObjectType.StoredProcedure:
    //                break;
    //            default:
    //                break;
    //        }
    //    }

    //    private void GenerateTableRowCollectionClass(SharpCodeProvider codeProvider, string data)
    //    {
    //        string entityBaseType = string.Format("EntityBase<{0}, {1}>", _currentObject.ClassName, entityRowClassName);
    //        codeProvider.WriteField(new AccessModifiers[] { AccessModifiers.amPrivate }, entityBaseType, "_entity", null);
    //        codeProvider.WriteConstructor(new AccessModifiers[] { AccessModifiers.amPublic }, entityRowCollectionClassName, new string[] { entityBaseType, "List<EntityColumn>" }, new string[] { "entity", "columns" }, TableConstructorRowCollectionContent, new string[] { "entity.Table", "columns" });
    //        codeProvider.WriteMethod(new AccessModifiers[] { AccessModifiers.amPublic, AccessModifiers.amOverride }, entityRowClassName, "AddNew", null, null, AddNewContent);
    //    }

    //    public void TableConstructorRowCollectionContent(SharpCodeProvider codeProvider, object data)
    //    {
    //        codeProvider.WriteAssignment("_entity", "entity");
    //    }

    //    public void AddNewContent(SharpCodeProvider codeProvider, object data)
    //    {
    //        codeProvider.WriteCodeLine("base._parentTable.BeginLoadData();");
    //        codeProvider.WriteCodeLine("DataRow row = _parentTable.NewRow();");
    //        codeProvider.WriteCodeLine("row.BeginEdit();");
    //        codeProvider.WriteCodeLine("base.InitializeDefaultValues(row);");
    //        codeProvider.WriteCodeLine("row.EndEdit();");
    //        codeProvider.WriteCodeLine("_parentTable.Rows.Add(row);");
    //        codeProvider.WriteCodeLine("_parentTable.EndLoadData();");

    //        codeProvider.WriteCodeLine(string.Format("{0} eRow = new {0}(row, _entity);", entityRowClassName));
    //        codeProvider.WriteCodeLine("_internalTable.Add(eRow);");
    //        codeProvider.WriteCodeLine("return eRow;");
    //    }

    //    #endregion

    //    #region EntityRow Class

    //    private void classRowGeneration(SharpCodeProvider codeProvider, object data)
    //    {
    //        switch (_currentObject.ObjectType)
    //        {
    //            case CodeGen.Enums.SqlObjectType.Table:
    //            case CodeGen.Enums.SqlObjectType.View:
    //                GenerateTableRowClass(codeProvider, (string)data);
    //                break;
    //            case CodeGen.Enums.SqlObjectType.StoredProcedure:
    //                break;
    //            default:
    //                break;
    //        }
    //    }

    //    private IColumn _currentColumn;
    //    private SqlRelation _currentRelation;
    //    private Dictionary<string, string> _propertyNames = new Dictionary<string, string>();
    //    private void GenerateTableRowClass(SharpCodeProvider codeProvider, string data)
    //    {
    //        foreach (SqlRelation relation in _currentObject.RelatedEntities)
    //        {
    //            _currentRelation = relation;
    //            string className = GetClassNameByName(relation.RefEntity);
    //            if (string.IsNullOrEmpty(className))
    //            {
    //                continue;
    //            }
    //            className = relation.RelationType == CodeGen.Common.Enums.SqlRelationType.OneToMany ? className : string.Format("{0}Row", className);
    //            codeProvider.WriteCodeLine(string.Format("#region {0}Relation", className));
    //            codeProvider.WriteField(new AccessModifiers[] { AccessModifiers.amPrivate }, className, codeProvider.GetPrivatePropertyName(relation.PropertyName), "null");
    //            codeProvider.WriteProperty(new AccessModifiers[] { AccessModifiers.amPublic }, className, relation.PropertyName, GetTableRelation, null, false, null, false);
    //            codeProvider.WriteMethod(new AccessModifiers[] { AccessModifiers.amPublic }, null, string.Format("Invalidate_{0}", relation.PropertyName), new string[] { className }, new string[] { "entity" }, InvalidateTableRelation);
    //            codeProvider.WriteCodeLine("#endregion");
    //        }

    //        ITable table = _currentObject.Data as ITable;
    //        foreach (IColumn col in table.Columns)
    //        {
    //            _currentColumn = col;
    //            codeProvider.WriteProperty(new AccessModifiers[] { AccessModifiers.amPublic }, col.DataType.ToSystemDataType(col.Nullable), col.Name, GetTableRowColumn, SetTableRowColumn, true, null, false);
    //        }
    //        string entityBaseType = string.Format("EntityBase<{0}, {1}>", _currentObject.ClassName, entityRowClassName);
    //        codeProvider.WriteConstructor(new AccessModifiers[] { AccessModifiers.amPublic }, entityRowClassName, new string[] { "DataRow", entityBaseType }, new string[] { "row", "entity" }, null, new string[] { "row", "entity" });
    //    }

    //    private void InvalidateTableRelation(SharpCodeProvider codeProvider, object data)
    //    {
    //        codeProvider.WriteCodeLine("if (entity != null)");
    //        codeProvider.WriteBegin();
    //        codeProvider.WriteCodeLine("entity.Dispose();");
    //        codeProvider.WriteCodeLine("entity = null;");
    //        codeProvider.WriteEnd();
    //    }

    //    private void GetTableRelation(SharpCodeProvider codeProvider, object data)
    //    {
    //        string prvFld = codeProvider.GetPrivatePropertyName(_currentRelation.PropertyName);
    //        string className = GetClassNameByName(_currentRelation.RefEntity);
    //        className = _currentRelation.RelationType == CodeGen.Common.Enums.SqlRelationType.OneToMany ? className : string.Format("{0}Row", className);

    //        codeProvider.WriteCodeLine(string.Format("if ({0} == null)", prvFld));
    //        codeProvider.WriteBegin();
    //        codeProvider.WriteAssignment(prvFld, string.Format("new {0}();", className));
    //        string colFilter = string.Empty;
    //        foreach (KeyValuePair<string, string> fkCol in _currentRelation.Columns)
    //        {
    //            colFilter += string.Format("{0}.{1} == {2} && ", prvFld, fkCol.Value, fkCol.Key);
    //        }
    //        if (colFilter.Length > 0)
    //        {
    //            colFilter = colFilter.Substring(0, colFilter.Length - 4);
    //        }
    //        codeProvider.WriteCodeLine(string.Format("{0}.Fill({1});", prvFld, colFilter));
    //        codeProvider.WriteEnd();
    //        codeProvider.WriteCodeLine(string.Format("return {0};", prvFld));
    //    }

    //    private void GetTableRowColumn(SharpCodeProvider codeProvider, object data)
    //    {
    //        codeProvider.WriteCodeLine(string.Format("return ({0})base[\"{1}\"];", _currentColumn.DataType.ToSystemDataType(_currentColumn.Nullable), _currentColumn.Name));
    //    }

    //    private void SetTableRowColumn(SharpCodeProvider codeProvider, object data)
    //    {
    //        SqlRelation relation = GetRelationByColumn(_currentColumn.Name);
    //        if (relation != null)
    //        {
    //            codeProvider.WriteCodeLine(string.Format("if (!base[\"{0}\"].Equals(value))", _currentColumn.Name));
    //            codeProvider.WriteBegin();
    //            codeProvider.WriteCodeLine(string.Format("Invalidate_{0}({1});", _currentRelation.PropertyName, codeProvider.GetPrivatePropertyName(_currentRelation.PropertyName)));
    //            codeProvider.WriteEnd();
    //        }
    //        codeProvider.WriteCodeLine(string.Format("base[\"{0}\"] = value;", _currentColumn.Name));
    //    }

    //    private string GetClassNameByName(string name)
    //    {
    //        SqlObjectCollection collection = _host.ObjectCollection;
    //        foreach (SqlObject obj in collection)
    //        {
    //            ITable table = obj.Data as ITable;
    //            if (table != null)
    //            {
    //                if (table.Name == name)
    //                {
    //                    return obj.ClassName;
    //                }
    //            }
    //        }
    //        return string.Empty;
    //    }

    //    #endregion

    //    private SqlRelation GetRelationByColumn(string columnName)
    //    {
    //        foreach (SqlRelation relation in _currentObject.RelatedEntities)
    //        {
    //            foreach (KeyValuePair<string, string> col in relation.Columns)
    //            {
    //                if (col.Key == columnName)
    //                {
    //                    return relation;
    //                }
    //            }
    //        }
    //        return null;
    //    }


    //    #endregion

    //    #region Mod
    //    private void EntryPointMod(SharpCodeProvider codeProvider)
    //    {
    //        codeProvider.WriteUsing("System");
    //        codeProvider.WriteUsing("System.Collections.Generic");
    //        codeProvider.WriteUsing("System.Data");
    //        codeProvider.WriteUsing("ICFramework.Business.DataLayer");
    //        codeProvider.WriteUsing("ICFramework.Common.DataLayer");
    //        codeProvider.WriteNamespace(Host.OutNamespace, new SharpCodeProvider.WriterDelegate[] { classNSMod });
    //    }

    //    private void classNSMod(SharpCodeProvider codeProvider, object data)
    //    {
    //        ITable table = _currentObject.Data as ITable;
    //        codeProvider.WriteClass(new AccessModifiers[] { AccessModifiers.amPublic }, true, _currentObject.ClassName, null, null);
    //    }
    //    #endregion

    //    #region ICodeGenTemplate Members

    //    private ICodeGenHost _host;
    //    public ICodeGenHost Host
    //    {
    //        get { return _host; }
    //    }

    //    public string Name
    //    {
    //        get { return "ICFramework template"; }
    //    }

    //    public string Description
    //    {
    //        get { return "ICFramework MSSql template"; }
    //    }

    //    public string Author
    //    {
    //        get { return "Ionut Chichisan"; }
    //    }

    //    public string Version
    //    {
    //        get { return "1.0.0.0"; }
    //    }

    //    public void Initialize(ICodeGenHost host)
    //    {
    //        _host = host;
    //        try
    //        {
    //            //System.Diagnostics.Debugger.Break();
    //            foreach (SqlObject obj in _host.ObjectCollection)
    //            {
    //                SharpCodeProvider codeProvider1 = null;
    //                SharpCodeProvider codeProvider2 = null;
    //                _currentObject = obj;
    //                try
    //                {
    //                    _host.Feedback(this, string.Format("Generating class {0}", obj.ClassName));
    //                    string fileName = Path.GetFileNameWithoutExtension(obj.FileName);
    //                    string extension = Path.GetExtension(obj.FileName);
    //                    string path = Path.GetDirectoryName(obj.FileName);
    //                    string pathGenerated = Path.Combine(path, string.Format("{0}.generated{1}", fileName, extension));

    //                    codeProvider1 = new SharpCodeProvider(pathGenerated);
    //                    EntryPointGenerated(codeProvider1);

    //                    codeProvider2 = new SharpCodeProvider(obj.FileName);
    //                    EntryPointMod(codeProvider2);
    //                }
    //                catch (Exception ex)
    //                {
    //                    _host.Feedback(this, string.Format("Error generating template for class {0}. Error Message: {1}", obj.ClassName, ex.ToString()));
    //                }
    //                finally
    //                {
    //                    codeProvider1.Dispose();
    //                    codeProvider2.Dispose();
    //                }
    //            }
    //        }
    //        catch (Exception ex)
    //        {
    //            _host.Feedback(this, ex.ToString());
    //        }
    //    }

    //    public void Dispose()
    //    {
    //    }

    //    #endregion

    //    #region ICodeGenTemplate Members


    //    public void OnSqlObject(SharpCodeProvider provider, SqlObject sqlObject, bool classGeneration)
    //    {
    //        throw new NotImplementedException();
    //    }

    //    #endregion
    //}
}
